package drds.plus.rule_engine.column_value_enumerator.handler;

import drds.plus.common.model.comparative.Comparative;
import drds.plus.common.thread_local.ThreadLocalMap;
import drds.plus.rule_engine.column_value_enumerator.DateEnumerationParameter;

import java.util.Calendar;
import java.util.Date;
import java.util.Set;

/**
 * 基于时间类型的枚举器
 */
public class DatePartDiscontinousRangeEnumerateHandler extends PartDiscontinousRangeEnumerateHandler {

    private static final long LIMIT_UNIT_OF_DATE = 1L;
    private static final String DATE_ENUMERATOR = "DATE_ENUMERATOR";
    private static final int DEFAULT_DATE_ATOMIC_VALUE = 1;

    protected Comparative changeGreaterThanToGreaterThanOrEqual(Comparative from) {
        if (from.getComparison() == Comparative.greater_than) {
            Date date = (Date) from.getValue();
            long time = date.getTime() + LIMIT_UNIT_OF_DATE;
            return new Comparative(Comparative.greater_than_or_equal, new Date(time));
        }
        return from;
    }

    protected Comparative changeLessThanToLessThanOrEqual(Comparative to) {
        if (to.getComparison() == Comparative.less_than) {
            Date date = (Date) to.getValue();
            long time = date.getTime() - LIMIT_UNIT_OF_DATE;
            return new Comparative(Comparative.less_than_or_equal, new Date(time));
        }
        return to;
    }

    protected Comparable getOneStep(Comparable source, Comparable atomIncreaseValue) {
        DateEnumerationParameter dateEnumerationParameter = getDateEnumerationParameter(atomIncreaseValue);
        Calendar cal = getCalendar((Date) source);
        cal.add(dateEnumerationParameter.calendarFieldType, dateEnumerationParameter.atomicIncreaseNumber);
        return cal.getTime();
    }

    @SuppressWarnings({"unchecked", "rawtypes"})

    protected boolean inputCloseRangeGreaterThanMaxFieldOfDifination(Comparable from, Comparable to, Integer cumulativeTimes, Comparable<?> atomIncrValue) {
        if (cumulativeTimes == null) {
            return false;
        }
        Calendar cal = getCalendar((Date) from);
        int rangeSet = cumulativeTimes;
        if (atomIncrValue instanceof Integer) {
            // 兼容老实现，对应#gmt,1,7#这种
            cal.add(Calendar.DATE, rangeSet * (Integer) atomIncrValue);
        } else if (atomIncrValue instanceof DateEnumerationParameter) {
            // 对应#gmt,1_month,12这样的情况
            DateEnumerationParameter dep = (DateEnumerationParameter) atomIncrValue;
            cal.add(dep.calendarFieldType, rangeSet * dep.atomicIncreaseNumber);
        } else if (atomIncrValue == null) {
            // 兼容老实现，对应没有#gmt#.这种普通的情况，
            cal.add(Calendar.DATE, rangeSet);
        } else {
            throwNotSupportIllegalArgumentException(atomIncrValue);
        }

        return to.compareTo(cal.getTime()) >= 0;
    }

    private void throwNotSupportIllegalArgumentException(Object arg) {
        throw new IllegalArgumentException("不能识别的类型:" + arg + " .type is" + arg.getClass());
    }

    public void exhaust(Comparative from, Integer cumulativeTime, Comparable<?> atomIncreaseValue, Set<Object> returnSet) {
        DateEnumerationParameter dateEnumerationParameter = getDateEnumerationParameter(atomIncreaseValue);
        // 把> < 替换为>= <=
        from = changeGreaterThanToGreaterThanOrEqual(from);
        from = changeLessThanToLessThanOrEqual(from);

        Calendar cal = getCalendar((Date) from.getValue());
        int comparasion = from.getComparison();
        if (comparasion == Comparative.greater_than_or_equal) {
            // 添加当前时间，因为当前时间内已经是大于等于了。
            returnSet.add(cal.getTime());
            // 减少一次迭代，因为已经加了当前时间
            for (int i = 0; i < cumulativeTime - 1; i++) {
                cal.add(dateEnumerationParameter.calendarFieldType, dateEnumerationParameter.atomicIncreaseNumber);
                returnSet.add(cal.getTime());
            }
        } else if (comparasion == Comparative.less_than_or_equal) {
            returnSet.add(cal.getTime());
            for (int i = 0; i < cumulativeTime - 1; i++) {
                cal.add(dateEnumerationParameter.calendarFieldType, -1 * dateEnumerationParameter.atomicIncreaseNumber);
                returnSet.add(cal.getTime());
            }
        }
    }

    /**
     * 识别data自增参数
     */
    protected DateEnumerationParameter getDateEnumerationParameter(Comparable<?> comparable) {
        DateEnumerationParameter dateEnumerationParameter = null;
        if (comparable == null) {
            dateEnumerationParameter = new DateEnumerationParameter(DEFAULT_DATE_ATOMIC_VALUE);
        } else if (comparable instanceof Integer) {
            dateEnumerationParameter = new DateEnumerationParameter((Integer) comparable);
        } else if (comparable instanceof DateEnumerationParameter) {
            dateEnumerationParameter = (DateEnumerationParameter) comparable;
        } else {
            throwNotSupportIllegalArgumentException(comparable);
        }
        return dateEnumerationParameter;
    }

    private Calendar getCalendar(Date date2BeSet) {
        // 优化重用一下Calendar
        Calendar cal = (Calendar) ThreadLocalMap.get(DATE_ENUMERATOR);
        if (cal == null) {
            cal = Calendar.getInstance();
            ThreadLocalMap.put(DATE_ENUMERATOR, cal);
        }
        cal.setTime(date2BeSet);
        return cal;
    }
}
